package com.webserver.controller;

import com.webserver.controller.annotations.Controller;
import com.webserver.controller.annotations.RequestMapping;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

/**
 * 该类用于维护请求路径与对应的业务处理类和方法-
 */
public class HandlerMapping {

    /**
     * 保存每个请求路径与对应的业务处理方法
     * key:请求
     * value:处理该请求的业务方法
     *
     * 例如:
     *  key:./myweb/regUser
     *  value:MethodMapping{
     *      Object Controller => UserController的实例
     *      Method method => reg方法
     *  }
     */
    private static Map<String,MethodMapping> mapping = new HashMap<>();

    //静态块
    static {
        try {
            initMapping();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static void initMapping() throws URISyntaxException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        /*
            1:扫描com.webserver.controller包下的所有类
            2:利用反射机制加载这些类
            3:判断该类是否使用注解@Controller标注,没有则忽略
            4:扫描该类中的所有方法,并判断该方法是否使用注解@RequestMapping标注,没有的忽略
            5:将RequsetMapping中的参数获取到(该方法对应的请求路径)并作为一个key.
                实例化当前Collection并和当前方法对象(Method对象)组成一个MethodMapping作为value
                存入到mapping这个Map
         */
        File dir = new File(
                HandlerMapping.class.getClassLoader().getResource(
                        "./com/webserver/controller"
                ).toURI()
        );

        File[] subs = dir.listFiles(f -> f.getName().endsWith(".class"));


        for (File sub : subs) {
            String className = sub.getName().substring(0,sub.getName().indexOf("."));
            Class cls = Class.forName("com.webserver.controller."+className);
            //判断是否有注解@Controller
            if (cls.isAnnotationPresent(Controller.class)){
                //实例化这个Controller
                Object obj = cls.newInstance();

                //获取所有方法
                Method[] methods = cls.getDeclaredMethods();
                for (Method method : methods){
                    //是否有注解@RequestMapping
                    if (method.isAnnotationPresent(RequestMapping.class)){
                        //获取该方法的请求路径
                        RequestMapping rm = method.getAnnotation(RequestMapping.class);
                        String key = rm.value();
                        MethodMapping value = new MethodMapping(obj, method);
                        mapping.put(key, value);
                    }
                }
            }

        }

    }

    /**
     * 根据给定的请求路径获取处理该路径的业务方法
     * @param path
     * @return
     */
    public static MethodMapping getMethod(String path){
        return mapping.get(path);
    }


    //静态内部类
    /*
        当前类的每一个实例对用于记录一个业务方法以及该方法所属的Controller对象
     */
    public static class MethodMapping{
        private Object controller;
        private Method method;

        //构造器
        public MethodMapping(Object controller, Method method) {
            this.controller = controller;
            this.method = method;
        }

        public Object getController() {
            return controller;
        }

        public void setController(Object controller) {
            this.controller = controller;
        }

        public Method getMethod() {
            return method;
        }

        public void setMethod(Method method) {
            this.method = method;
        }
    }
}
